module EncDec (
    input clk_i,
    input rst_n_i,
    
    input Mode_i,               //1: enc 0:dec
    input Data_Valid_i,
    input [1023:0] RoundKey_i,
    input [127:0]  Data_i,

    output Data_Ready,
    output [127:0] Data_o 
);

//------input-----------------------------------------
wire [31:0] RK[0:31];
reg [31:0] X_iter[0:35];
generate
    for (genvar i = 0; i<32 ; i=i+1 ) begin
        assign RK[i] = RoundKey_i[(i+1)*32-1:i*32];
    end
endgenerate

always @(*) begin
    X_iter[0] = Data_i[127:96];
    X_iter[1] = Data_i[95:64];
    X_iter[2] = Data_i[63:32];
    X_iter[3] = Data_i[31:0];
end

//--------counter---------------------------------------
reg [7:0] cnt;
reg Data_Valid_r;
wire start;
wire finished;
always @(posedge clk_i ) begin
    if(!rst_n_i) begin
        Data_Valid_r <= 0;
    end
    else begin
        Data_Valid_r <= Data_Valid_i;
    end
end
always @(posedge clk_i ) begin
    if(!rst_n_i || start) begin
        cnt <= 0;
    end
    else if(Data_Valid_i && !finished) begin
        cnt <= cnt + 1;
    end
    else if(finished) begin
        cnt <= 8'd32;
    end
end
assign start = Data_Valid_i & (!Data_Valid_r);
assign finished = (cnt == 8'd31);

//-----------------------------------------------------
reg [31:0] x0_i, x1_i, x2_i, x3_i;
reg [31:0] rk_i;
wire [31:0] x4_o;

always @(*) begin
    case (cnt)
    0 : begin
        x0_i = X_iter[0];
        x1_i = X_iter[1];
        x2_i = X_iter[2];
        x3_i = X_iter[3];
        rk_i = (Mode_i)? RK[0] : RK[31];
    end
    1 : begin
        x0_i = X_iter[1];
        x1_i = X_iter[2];
        x2_i = X_iter[3];
        x3_i = X_iter[4];
        rk_i = (Mode_i)? RK[1] : RK[30];
    end
    2 : begin
        x0_i = X_iter[2];
        x1_i = X_iter[3];
        x2_i = X_iter[4];
        x3_i = X_iter[5];
        rk_i = (Mode_i)? RK[2] : RK[29];
    end
    3 : begin
        x0_i = X_iter[3];
        x1_i = X_iter[4];
        x2_i = X_iter[5];
        x3_i = X_iter[6];
        rk_i = (Mode_i)? RK[3] : RK[28];
    end
    4 : begin
        x0_i = X_iter[4];
        x1_i = X_iter[5];
        x2_i = X_iter[6];
        x3_i = X_iter[7];
        rk_i = (Mode_i)? RK[4] : RK[27];
    end
    5 : begin
        x0_i = X_iter[5];
        x1_i = X_iter[6];
        x2_i = X_iter[7];
        x3_i = X_iter[8];
        rk_i = (Mode_i)? RK[5] : RK[26];
    end
    6 : begin
        x0_i = X_iter[6];
        x1_i = X_iter[7];
        x2_i = X_iter[8];
        x3_i = X_iter[9];
        rk_i = (Mode_i)? RK[6] : RK[25];
    end
    7 : begin
        x0_i = X_iter[7];
        x1_i = X_iter[8];
        x2_i = X_iter[9];
        x3_i = X_iter[10];
        rk_i = (Mode_i)? RK[7] : RK[24];
    end
    8 : begin
        x0_i = X_iter[8];
        x1_i = X_iter[9];
        x2_i = X_iter[10];
        x3_i = X_iter[11];
        rk_i = (Mode_i)? RK[8] : RK[23];
    end
    9 : begin
        x0_i = X_iter[9];
        x1_i = X_iter[10];
        x2_i = X_iter[11];
        x3_i = X_iter[12];
        rk_i = (Mode_i)? RK[9] : RK[22];
    end
    10 : begin
        x0_i = X_iter[10];
        x1_i = X_iter[11];
        x2_i = X_iter[12];
        x3_i = X_iter[13];
        rk_i = (Mode_i)? RK[10] : RK[21];
    end
    11 : begin
        x0_i = X_iter[11];
        x1_i = X_iter[12];
        x2_i = X_iter[13];
        x3_i = X_iter[14];
        rk_i = (Mode_i)? RK[11] : RK[20];
    end
    12 : begin
        x0_i = X_iter[12];
        x1_i = X_iter[13];
        x2_i = X_iter[14];
        x3_i = X_iter[15];
        rk_i = (Mode_i)? RK[12] : RK[19];
    end
    13 : begin
        x0_i = X_iter[13];
        x1_i = X_iter[14];
        x2_i = X_iter[15];
        x3_i = X_iter[16];
        rk_i = (Mode_i)? RK[13] : RK[18];
    end
    14 : begin
        x0_i = X_iter[14];
        x1_i = X_iter[15];
        x2_i = X_iter[16];
        x3_i = X_iter[17];
        rk_i = (Mode_i)? RK[14] : RK[17];
    end
    15 : begin
        x0_i = X_iter[15];
        x1_i = X_iter[16];
        x2_i = X_iter[17];
        x3_i = X_iter[18];
        rk_i = (Mode_i)? RK[15] : RK[16];
    end
    16 : begin
        x0_i = X_iter[16];
        x1_i = X_iter[17];
        x2_i = X_iter[18];
        x3_i = X_iter[19];
        rk_i = (Mode_i)? RK[16] : RK[15];
    end
    17 : begin
        x0_i = X_iter[17];
        x1_i = X_iter[18];
        x2_i = X_iter[19];
        x3_i = X_iter[20];
        rk_i = (Mode_i)? RK[17] : RK[14];
    end
    18 : begin
        x0_i = X_iter[18];
        x1_i = X_iter[19];
        x2_i = X_iter[20];
        x3_i = X_iter[21];
        rk_i = (Mode_i)? RK[18] : RK[13];
    end
    19 : begin
        x0_i = X_iter[19];
        x1_i = X_iter[20];
        x2_i = X_iter[21];
        x3_i = X_iter[22];
        rk_i = (Mode_i)? RK[19] : RK[12];
    end
    20 : begin
        x0_i = X_iter[20];
        x1_i = X_iter[21];
        x2_i = X_iter[22];
        x3_i = X_iter[23];
        rk_i = (Mode_i)? RK[20] : RK[11];
    end
    21 : begin
        x0_i = X_iter[21];
        x1_i = X_iter[22];
        x2_i = X_iter[23];
        x3_i = X_iter[24];
        rk_i = (Mode_i)? RK[21] : RK[10];
    end
    22 : begin
        x0_i = X_iter[22];
        x1_i = X_iter[23];
        x2_i = X_iter[24];
        x3_i = X_iter[25];
        rk_i = (Mode_i)? RK[22] : RK[9];
    end
    23 : begin
        x0_i = X_iter[23];
        x1_i = X_iter[24];
        x2_i = X_iter[25];
        x3_i = X_iter[26];
        rk_i = (Mode_i)? RK[23] : RK[8];
    end
    24 : begin
        x0_i = X_iter[24];
        x1_i = X_iter[25];
        x2_i = X_iter[26];
        x3_i = X_iter[27];
        rk_i = (Mode_i)? RK[24] : RK[7];
    end
    25 : begin
        x0_i = X_iter[25];
        x1_i = X_iter[26];
        x2_i = X_iter[27];
        x3_i = X_iter[28];
        rk_i = (Mode_i)? RK[25] : RK[6];
    end
    26 : begin
        x0_i = X_iter[26];
        x1_i = X_iter[27];
        x2_i = X_iter[28];
        x3_i = X_iter[29];
        rk_i = (Mode_i)? RK[26] : RK[5];
    end
    27 : begin
        x0_i = X_iter[27];
        x1_i = X_iter[28];
        x2_i = X_iter[29];
        x3_i = X_iter[30];
        rk_i = (Mode_i)? RK[27] : RK[4];
    end
    28 : begin
        x0_i = X_iter[28];
        x1_i = X_iter[29];
        x2_i = X_iter[30];
        x3_i = X_iter[31];
        rk_i = (Mode_i)? RK[28] : RK[3];
    end
    29 : begin
        x0_i = X_iter[29];
        x1_i = X_iter[30];
        x2_i = X_iter[31];
        x3_i = X_iter[32];
        rk_i = (Mode_i)? RK[29] : RK[2];
    end
    30 : begin
        x0_i = X_iter[30];
        x1_i = X_iter[31];
        x2_i = X_iter[32];
        x3_i = X_iter[33];
        rk_i = (Mode_i)? RK[30] : RK[1];
    end
    31 : begin
        x0_i = X_iter[31];
        x1_i = X_iter[32];
        x2_i = X_iter[33];
        x3_i = X_iter[34];
        rk_i = (Mode_i)? RK[31] : RK[0];
    end
    default : begin
        x0_i = 32'b0;
        x1_i = 32'b0;
        x2_i = 32'b0;
        x3_i = 32'b0;
        rk_i = 32'b0;
 
    end
            
    endcase
end

Round_Fuction EDC(
     .kgen_en(1'b0),     //1: 生成轮密钥 0： 生成加解密数据    
     .x0_i(x0_i),
     .x1_i(x1_i),
     .x2_i(x2_i),
     .x3_i(x3_i),
     .rk_i(rk_i),        
     .x4_o(x4_o)
);

generate
    for (genvar i = 0; i < 32 ; i = i+1 ) begin
        always @(posedge clk_i ) begin
            if(!rst_n_i) begin
                X_iter[i+4] <= 32'b0;
            end
            else if(cnt == i) begin
                X_iter[i+4] <= x4_o;
            end
        end        
    end
endgenerate

//----output----------------------------------------
assign Data_Ready = (cnt == 8'd32);
assign Data_o = {X_iter[35],X_iter[34],X_iter[33],X_iter[32]};

endmodule //EncDec
